package edu.scsu.csci.core;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

import edu.scsu.csci.util.ReflectionUtil;


/**
 * An adapter for the {@link java.lang.reflection.Method}.
 * 
 * @author Maqbool Khan
 * @since jdk 1.5
 * @see
 */
public class ActionMethod {

	/**
	 * command method.
	 */
	private Method method;
	
		
	/**
	 * Returns an instance of the action method.
	 * 
	 * @param className
	 * @param methodName
	 * @return
	 */
	public static ActionMethod getInstance(Object domainObject, String methodName)	{
		try {
			Method method = ReflectionUtil.getMethod(domainObject.getClass(), methodName);
			return new ActionMethod(method);
		}catch(Exception e)	{
			throw new ReflectionUtil.InstantiationException("Unable to instantiate the ActionMethod object: " + e.getMessage(), e);
		}
	}
	
	/**
	 * @param method
	 */
	public ActionMethod(Method method) {
		this.method = method;
	}
	
	/**
	 * @param businessObject	business object on which the action should be invoked
	 * @param parameters		the parameters for the action
	 * @return					the value returned by the action
	 * @throws ActionInvocationException
	 */
	public Object invoke(Object businessObject, Object... parameters)
			throws ActionInvocationException {
		
		if(this.method.getParameterTypes().length == 0){
			return ReflectionUtil.invoke(businessObject, this.method);
		}
		return ReflectionUtil.invoke(businessObject, this.method, parameters);
	}

	/**
	 * Returns the method's name
	 * 
	 * @return the name
	 */
	public String getName() {
		return method.getName();
	}

	/**
	 * Returns true if the method contains annotations.
	 * 
	 * @param <T>
	 * @param type
	 * @return
	 */
	public <T extends Annotation> boolean isAnnotationPresent(Class<T> type) {
		return this.method.isAnnotationPresent(type);
	}
	
	
	/**
	 * Returns the annotation defined for <code>method</code> with <code>annotationClass</code> as the class.
	 * 
	 * @param <T>
	 * @param annotationClass
	 * @return
	 */
	public <T extends Annotation> Annotation getAnnotation(Class<T> annotationClass)	{
		return this.method.getAnnotation(annotationClass);
	}
}
